package com.example.forum.controller;

import java.util.Date;
import java.util.List;
import java.util.Calendar;
import java.util.TimeZone;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.example.forum.common.AppResult;
import com.example.forum.common.ResultCode;
import com.example.forum.config.AppConfig;
import com.example.forum.model.Announcement;
import com.example.forum.model.User;
import com.example.forum.services.IAnnouncementService;
import com.example.forum.services.IUserService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;

/**
 * 系统公告控制器
 */
@RestController
@RequestMapping("/announcement")
@Api(tags = "系统公告接口")
@Slf4j
@Validated
public class AnnouncementController {

    @Resource
    private IAnnouncementService announcementService;
    
    @Resource
    private IUserService userService;
    
    /**
     * 获取有效公告列表
     * @param page 页码
     * @param size 每页条数
     * @return 公告列表
     */
    @GetMapping("/list")
    @ApiOperation("获取有效公告列表")
    public AppResult<List<Announcement>> getActiveAnnouncements(
            @ApiParam("页码") @RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
            @ApiParam("每页条数") @RequestParam(value = "size", required = false, defaultValue = "10") Integer size) {
        try {
            List<Announcement> announcements = announcementService.getActiveAnnouncements(page, size);
            int total = announcementService.countActiveAnnouncements();
            
            log.info("获取有效公告列表成功，页码: {}, 每页条数: {}, 总数: {}", page, size, total);
            
            return AppResult.success(announcements, total);
        } catch (Exception e) {
            log.error("获取有效公告列表失败，错误: {}", e.getMessage(), e);
            return AppResult.failed("获取公告列表失败");
        }
    }
    
    /**
     * 获取置顶公告
     * @return 置顶公告列表
     */
    @GetMapping("/top")
    @ApiOperation("获取置顶公告")
    public AppResult<List<Announcement>> getTopAnnouncements() {
        try {
            List<Announcement> announcements = announcementService.getTopAnnouncements();
            log.info("获取置顶公告成功，数量: {}", announcements.size());
            
            return AppResult.success(announcements);
        } catch (Exception e) {
            log.error("获取置顶公告失败，错误: {}", e.getMessage(), e);
            return AppResult.failed("获取置顶公告失败");
        }
    }
    
    /**
     * 获取公告详情
     * @param id 公告ID
     * @return 公告详情
     */
    @GetMapping("/detail")
    @ApiOperation("获取公告详情")
    public AppResult<Announcement> getAnnouncementDetail(
            @ApiParam("公告ID") @RequestParam("id") @NotNull Long id) {
        try {
            Announcement announcement = announcementService.getById(id);
            
            if (announcement == null) {
                log.warn("获取公告详情失败，公告不存在，ID: {}", id);
                return AppResult.failed("公告不存在");
            }
            
            // 增加浏览量
            announcementService.view(id);
            
            log.info("获取公告详情成功，ID: {}", id);
            
            return AppResult.success(announcement);
        } catch (Exception e) {
            log.error("获取公告详情失败，ID: {}, 错误: {}", id, e.getMessage(), e);
            return AppResult.failed("获取公告详情失败");
        }
    }
    
    /**
     * 创建公告
     * @param request HTTP请求
     * @param title 公告标题
     * @param content 公告内容
     * @param type 公告类型
     * @param isTop 是否置顶
     * @return 操作结果
     */
    @PostMapping("/create")
    @ApiOperation("创建公告")
    public AppResult<Long> createAnnouncement(
            HttpServletRequest request,
            @ApiParam("公告标题") @RequestParam("title") @NotBlank String title,
            @ApiParam("公告内容") @RequestParam("content") @NotBlank String content,
            @ApiParam("公告类型") @RequestParam(value = "type", required = false, defaultValue = "notice") String type,
            @ApiParam("是否置顶") @RequestParam(value = "isTop", required = false, defaultValue = "0") Byte isTop) {
        
        // 获取当前用户信息
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION);
        
        // 验证用户是否存在且有权限
        if (user == null) {
            log.warn("创建公告失败: 用户未登录");
            return AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        
        // 检查用户权限 (0为普通用户，1为管理员)
        if (user.getIsAdmin() == 0) {
            log.warn("创建公告失败: 用户无权限，用户ID: {}, 是否管理员: {}", user.getId(), user.getIsAdmin());
            return AppResult.failed(ResultCode.FAILED_FORBIDDEN);
        }
        
        try {
            // 验证公告类型
            if (!isValidAnnouncementType(type)) {
                log.warn("创建公告失败: 无效的公告类型 {}", type);
                return AppResult.failed("无效的公告类型");
            }
            
            // 创建公告对象
            Announcement announcement = new Announcement();
            announcement.setTitle(title);
            announcement.setContent(content);
            announcement.setType(type);
            announcement.setIsTop(isTop);
            announcement.setPublisherId(user.getId());
            announcement.setPublisherName(user.getNickname());
            
            // 显式设置创建时间和更新时间为当前时间（使用Asia/Shanghai时区）
            Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
            Date now = calendar.getTime();
            log.info("设置公告创建时间: {}", now);
            announcement.setCreateTime(now);
            announcement.setUpdateTime(now);
            
            // 保存公告
            Long announcementId = announcementService.create(announcement);
            
            log.info("创建公告成功，公告ID: {}, 标题: {}, 发布者ID: {}", announcementId, title, user.getId());
            
            return AppResult.success(announcementId);
        } catch (Exception e) {
            log.error("创建公告失败，错误: {}", e.getMessage(), e);
            return AppResult.failed("创建公告失败: " + e.getMessage());
        }
    }
    
    /**
     * 更新公告
     * @param request HTTP请求
     * @param id 公告ID
     * @param title 公告标题
     * @param content 公告内容
     * @param type 公告类型
     * @param isTop 是否置顶
     * @return 操作结果
     */
    @PostMapping("/update")
    @ApiOperation("更新公告")
    public AppResult<Boolean> updateAnnouncement(
            HttpServletRequest request,
            @ApiParam("公告ID") @RequestParam("id") @NotNull Long id,
            @ApiParam("公告标题") @RequestParam(value = "title", required = false) String title,
            @ApiParam("公告内容") @RequestParam(value = "content", required = false) String content,
            @ApiParam("公告类型") @RequestParam(value = "type", required = false) String type,
            @ApiParam("是否置顶") @RequestParam(value = "isTop", required = false) Byte isTop) {
        
        // 获取当前用户信息
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION);
        
        // 验证用户是否存在且有权限
        if (user == null) {
            log.warn("更新公告失败: 用户未登录");
            return AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        
        // 检查用户权限
        if (user.getIsAdmin() == 0) {
            log.warn("更新公告失败: 用户无权限，用户ID: {}, 是否管理员: {}", user.getId(), user.getIsAdmin());
            return AppResult.failed(ResultCode.FAILED_FORBIDDEN);
        }
        
        try {
            // 获取原公告信息
            Announcement existingAnnouncement = announcementService.getById(id);
            
            if (existingAnnouncement == null) {
                log.warn("更新公告失败: 公告不存在，ID: {}", id);
                return AppResult.failed("公告不存在");
            }
            
            // 验证公告类型
            if (type != null && !isValidAnnouncementType(type)) {
                log.warn("更新公告失败: 无效的公告类型 {}", type);
                return AppResult.failed("无效的公告类型");
            }
            
            // 更新公告对象
            Announcement announcement = new Announcement();
            announcement.setId(id);
            
            if (title != null && !title.isEmpty()) {
                announcement.setTitle(title);
            }
            
            if (content != null && !content.isEmpty()) {
                announcement.setContent(content);
            }
            
            if (type != null && !type.isEmpty()) {
                announcement.setType(type);
            }
            
            if (isTop != null) {
                announcement.setIsTop(isTop);
            }
            
            // 设置更新时间
            Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
            Date now = calendar.getTime();
            log.info("设置公告更新时间: {}", now);
            announcement.setUpdateTime(now);
            
            // 保存更新
            boolean success = announcementService.update(announcement);
            
            if (success) {
                log.info("更新公告成功，公告ID: {}, 更新者ID: {}", id, user.getId());
                return AppResult.success(true);
            } else {
                log.warn("更新公告失败，公告ID: {}, 更新者ID: {}", id, user.getId());
                return AppResult.failed("更新公告失败");
            }
        } catch (Exception e) {
            log.error("更新公告失败，ID: {}, 错误: {}", id, e.getMessage(), e);
            return AppResult.failed("更新公告失败: " + e.getMessage());
        }
    }
    
    /**
     * 删除公告
     * @param request HTTP请求
     * @param id 公告ID
     * @return 操作结果
     */
    @PostMapping("/delete")
    @ApiOperation("删除公告")
    public AppResult<Boolean> deleteAnnouncement(
            HttpServletRequest request,
            @ApiParam("公告ID") @RequestParam("id") @NotNull Long id) {
        
        // 获取当前用户信息
        HttpSession session = request.getSession(false);
        User user = (User) session.getAttribute(AppConfig.USER_SESSION);
        
        // 验证用户是否存在且有权限
        if (user == null) {
            log.warn("删除公告失败: 用户未登录");
            return AppResult.failed(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        
        // 检查用户权限
        if (user.getIsAdmin() == 0) {
            log.warn("删除公告失败: 用户无权限，用户ID: {}, 是否管理员: {}", user.getId(), user.getIsAdmin());
            return AppResult.failed(ResultCode.FAILED_FORBIDDEN);
        }
        
        try {
            // 获取原公告信息
            Announcement existingAnnouncement = announcementService.getById(id);
            
            if (existingAnnouncement == null) {
                log.warn("删除公告失败: 公告不存在，ID: {}", id);
                return AppResult.failed("公告不存在");
            }
            
            // 删除公告
            boolean success = announcementService.delete(id);
            
            if (success) {
                log.info("删除公告成功，公告ID: {}, 删除者ID: {}", id, user.getId());
                return AppResult.success(true);
            } else {
                log.warn("删除公告失败，公告ID: {}, 删除者ID: {}", id, user.getId());
                return AppResult.failed("删除公告失败");
            }
        } catch (Exception e) {
            log.error("删除公告失败，ID: {}, 错误: {}", id, e.getMessage(), e);
            return AppResult.failed("删除公告失败: " + e.getMessage());
        }
    }
    
    /**
     * 检查公告类型是否有效
     * @param type 公告类型
     * @return 是否有效
     */
    private boolean isValidAnnouncementType(String type) {
        return type != null && (
                type.equals("notice") || 
                type.equals("important") || 
                type.equals("system"));
    }
} 